// inventory_assembler.js

import { Engine } from "../engine";
import { DateUtil } from '../../utils/dateUtil';
import { CommonOrderStatus, OrderSortType, DocType } from "../common/docDefinition";
import { WareHouse } from "./warehouse";
import { CommodityBatch } from "./inventory";
import { CsDouble } from "../common/csDouble";
import { CsFundDouble } from "../common/csFundDouble";
import { DocBase } from "../common/docBase";
import { Util } from "../../utils/util";
import {OrderUtil} from "../../utils/orderUtil";

/// 过滤条件
export class InventoryAssemblerFilter {
    /// 单号
    inventoryId = null;

    /// 单据标题
    inventoryTitle = null;

    ///  状态 0 all, 1 未审核，2 已审核  for desktop and web  类型 CommonOrderStatus 中的code
    status = null;

    /// 规格商品名称
    subCommodityName = null;

    /// 源仓库 WareHouse
    srcWareHouse = null;

    /// 目标仓库 WareHouse
    targetWareHouse = null;

    /// 开始时间
    startDate = null;

    /// 结束时间
    endDate = null;

    /// 排序方式,默认按创建时间排序 OrderSortType 的code
    sortType = OrderSortType.CreateTime.code;

    /// 门店过滤
    storeId = null;

    /// 构造函数
    constructor({ storeId = null } = {}) {
        this.storeId = storeId || (Engine.profile?.filterStore?.id ?? null);
    }

    clear() {
        this.inventoryId = null;
        this.inventoryTitle = "";
        this.srcWareHouse = null;
        this.targetWareHouse = null;
        this.subCommodityName = null;
        this.startDate = null;
        this.endDate = null;
        this.status = null;
    }

    static clone(filter) {
        const cloned = new InventoryAssemblerFilter();
        cloned.inventoryId = filter.inventoryId;
        cloned.inventoryTitle = filter.inventoryTitle;
        cloned.srcWareHouse = filter.srcWareHouse;
        cloned.targetWareHouse = filter.targetWareHouse;
        cloned.subCommodityName = filter.subCommodityName;
        cloned.startDate = filter.startDate;
        cloned.endDate = filter.endDate;
        cloned.status = filter.status;
        cloned.sortType = filter.sortType;
        cloned.storeId = filter.storeId;
        return cloned;
    }

    _$InventoryAssemblerFilterToJson({ withState = false } = {}) {
        const ret = {};

        if (this.inventoryId != null && this.inventoryId.length > 0) {
            ret["a_lke_id"] = this.inventoryId;
        }
        if (this.status != null && this.status === CommonOrderStatus.WaitReview.code && withState) {
            ret['a_orderStatus'] = 0;
        }
        if (this.status != null && this.status === CommonOrderStatus.Passed.code && withState) {
            ret['a_orderStatus'] = 1;
        }
        if (this.inventoryTitle != null && this.inventoryTitle.length > 0) {
            ret["a_lke_orderTitle"] = this.inventoryTitle;
        }
        if (this.srcWareHouse != null) ret["ign_fromStorageId"] = this.srcWareHouse.id;
        if (this.targetWareHouse != null) ret["ign_toStorageId"] = this.targetWareHouse.id;

        if (this.subCommodityName != null && this.subCommodityName.length > 0) {
            ret["ign_specName"] = this.subCommodityName;
        }

        if (this.startDate != null && this.endDate != null && this.endDate > this.startDate) {
            /* 记录时间过滤
            ret["a_gte_createTime"] =
                DateUtil.formatDate(this.startDate, "yyyy-MM-dd HH:mm:ss");
            ret["a_lte_createTime"] =
                DateUtil.formatDate(this.endDate, "yyyy-MM-dd HH:mm:ss");
                */
            // 业务时间过滤
            ret["a_gte_businessTime"] =
                DateUtil.formatDate(this.startDate, "yyyy-MM-dd HH:mm:ss");
            ret["a_lte_businessTime"] =
                DateUtil.formatDate(this.endDate, "yyyy-MM-dd HH:mm:ss");
        } else if (this.startDate != null && this.endDate == null) {
            // 业务时间过滤
            ret["a_gte_businessTime"] =
                DateUtil.formatDate(this.startDate, "yyyy-MM-dd HH:mm:ss");
        } else if (this.endDate != null && this.startDate == null) {
            ret["a_lte_businessTime"] =
                DateUtil.formatDate(this.endDate, "yyyy-MM-dd HH:mm:ss");
        }

        if (this.sortType === OrderSortType.CreateTime.code) {
            ret["sort"] = "a.create_time desc";
            // ret["sort"] = "f.create_time";
        } else if (this.sortType === OrderSortType.OperationTime.code) {
            ret["sort"] = "a.business_time desc, a.create_time desc";
        }

        // 门店过滤
        if (this.storeId != null) {
            ret["storeId"] = this.storeId;
        }

        return ret;
    }

    toJson({ withState = false } = {}) {
        return this._$InventoryAssemblerFilterToJson({ withState });
    }
}

/// 组装拆卸单
export class InventoryAssembler extends DocBase {
    /// 源商品 CommodityBatch
    _orgCommodityList = [];

    /// 新商品 CommodityBatch
    _newCommodityList = [];

    /// 组装拆卸成本 CsFundDouble
    cost = null;

    /// 源仓库 WareHouse
    srcWareHouse = null;

    /// 目标 WareHouse
    targetWareHouse = null;

    /// 商品列表
    get orgCommodityList() {
        return [...this._orgCommodityList];
    }

    get newCommodityList() {
        return [...this._newCommodityList];
    }

    get newCommodityQuantity() {
        let value = CsDouble.zero();
        for (const item of this._newCommodityList) {
            value = value.add(item.count);
        }
        return value.value;
    }

    get srcCommodityQuantity() {
        let value = CsDouble.zero();
        for (const item of this._orgCommodityList) {
            value = value.add(item.count);
        }
        return value.value;
    }

    validateOrder() {
        if (this._orgCommodityList.length === 0) {
            return "请添加出库商品";
        }
        if (this._newCommodityList.length === 0) {
            return "请添加入库商品";
        }
        for (const item of this._orgCommodityList) {
            if (item.count.value <= 0) {
                return "请设置出库商品数量";
            }
        }
        for (const item of this._newCommodityList) {
            if (item.count.value <= 0) {
                return "请设置入库商品数量";
            }
        }
        //校验源和新商品是否有重复
        for (const item of this._orgCommodityList) {
            if (this._newCommodityList.some(element => element.commodity.id === item.commodity.id)) {
                return `出库商品和入库商品不能有重复! 重复商品: [${item.commodity.name}]`;
            }
        }
        return null;
    }

    /// 插入 batch CommodityBatch
    addCommodityBatch(batch, { isOrgCommodity }) {
        if (isOrgCommodity) {
            this._orgCommodityList.push(batch);
        } else {
            this._newCommodityList.push(batch);
        }
    }

    /// 更新商品列表 list CommodityBatch
    updateCommodityList(list, { isOrgCommodity }) {
        if (isOrgCommodity) {
            this._orgCommodityList = [...list];
        } else {
            this._newCommodityList = [...list];
        }
    }

    commodityList({ isOrgCommodity }) {
        return isOrgCommodity ? this.orgCommodityList : this.newCommodityList;
    }

    /// 插入 batch 或是更新数量 CommodityBatch
    /// 没有该商品，添加，如果有则增加数量
    addOrUpdateCommodityBatch(batch, { isOrgCommodity }) {
        const _commodityList = isOrgCommodity ? this._orgCommodityList : this._newCommodityList;

        const existCommodityList = _commodityList.filter(
            element => element.commodity.id === batch.commodity.id
        );
        if (existCommodityList.length === 0) {
            _commodityList.push(batch);
            return null;
        } else {
            existCommodityList[0].addCount(new CsDouble(1));
            return 1;
        }
    }

    /// 删除batch
    removeCommodityBatch(batch, { isOrgCommodity }) {
        const _commodityList = isOrgCommodity ? this._orgCommodityList : this._newCommodityList;
        const index = _commodityList.indexOf(batch);
        if (index !== -1) {
            _commodityList.splice(index, 1);
            return true;
        }
        return false;
    }

    /// 清除商品列表
    clearCommodity() {
        this._orgCommodityList = [];
        this._newCommodityList = [];
    }

    /// batch CommodityBatch
    indexOfCommodityBatch(batch, { isOrgCommodity }) {
        const _commodityList = isOrgCommodity ? this._orgCommodityList : this._newCommodityList;
        return _commodityList.indexOf(batch);
    }

    constructor({
        srcWareHouse,
        targetWareHouse,
        orgCommodityBatch = null,  // List<CommodityBatch>
        newCommodityBatch = null,  // List<CommodityBatch>

        // super param
        id,
        storeId,
        storeName,
        remark = "",
        operator = "",
        operatorId = "",
        docMaker = "",
        status = CommonOrderStatus.WaitReview,
        title = "",
        docCode = "",
        parentDocType = null, // DocType
        parentDocCode = "",
        parentDocTitle = "",
        sourceDocType = null, // DocType
        sourceDocCode = "",
        sourceDocTitle = "",
        cost = 0,

        /// 记录时间
        recordDate = null,
    }) {
        super({
            id,
            storeId,
            storeName,
            title,
            docCode,
            status,
            docType: DocType.ASSEMBLER,
            parentDocType,
            parentDocCode,
            parentDocTitle,
            sourceDocCode,
            sourceDocType,
            sourceDocTitle,
            recordDateTime: recordDate,
            operator,
            operatorId,
            docMaker,
            remark
        });

        this._orgCommodityList = orgCommodityBatch || [];
        this._newCommodityList = newCommodityBatch || [];
        this.cost = new CsFundDouble(cost);
        this.srcWareHouse = srcWareHouse;
        this.targetWareHouse = targetWareHouse;
    }

    static empty({
        operator = "",
        operatorId = "",
        storeId = null,
        storeName = null,
        cost = 0,
    } = {}) {
        // 设置默认门店
        let store = Engine.profile?.currentStore;
        if (storeId == null && store != null) {
            storeId = store.id;
            storeName = store.name;
        }




        let order = new InventoryAssembler({
            srcWareHouse: WareHouse.empty(),
            targetWareHouse: WareHouse.empty(),
            id: "",
            title: "",
            docCode: "",
            status: CommonOrderStatus.WaitReview,
            docType: DocType.ASSEMBLER,
            parentDocType: null,
            parentDocCode: "",
            parentDocTitle: "",
            sourceDocCode: "",
            sourceDocType: null,
            sourceDocTitle: "",
            operator: operator || Engine.profile?.nickName,
            operatorId: operatorId || Engine.profile?.id,
            docMaker: "",
            storeId,
            storeName,
            remark: "",
            cost
        });

        order.srcWareHouse = OrderUtil.getOrderDefaultWarehouse({
            storeId: order.storeId,
            curWarehouse: order.srcWareHouse
        });

        order.targetWareHouse = OrderUtil.getOrderDefaultWarehouse({
            storeId: order.storeId,
            curWarehouse: order.targetWareHouse
        });

        return order
    }

    static clone(data) {
        const baseOrder = DocBase.clone(data);

        const instance = new InventoryAssembler({
            srcWareHouse: WareHouse.clone(data.srcWareHouse),
            targetWareHouse: WareHouse.clone(data.targetWareHouse),
            orgCommodityBatch: [],
            newCommodityBatch: [],
            cost: data.cost,
            id: data.id,
            storeId: data.storeId,
            storeName: data.storeName,
            title: data.title,
            docCode: data.docCode,
            status: data.status,
            parentDocType: data.parentDocType,
            parentDocCode: data.parentDocCode,
            parentDocTitle: data.parentDocTitle,
            sourceDocType: data.sourceDocType,
            sourceDocCode: data.sourceDocCode,
            sourceDocTitle: data.sourceDocTitle,
            operator: data.operator,
            operatorId: data.operatorId,
            docMaker: data.docMaker,
            remark: data.remark,
            recordDate: data.recordDate
        });

        Object.assign(instance, baseOrder);

        for (const element of data._orgCommodityList) {
            instance._orgCommodityList.push(CommodityBatch.clone(element));
        }

        for (const element of data._newCommodityList) {
            instance._newCommodityList.push(CommodityBatch.clone(element));
        }

        return instance;
    }

    /// 复制
    resetForCopy({ removeParentAndSourceData = true } = {}) {
        super.resetForCopy({ removeParentAndSourceData });
        // 清除商品列表id
        for (const element of this._orgCommodityList) {
            element.id = "";
        }

        for (const element of this._newCommodityList) {
            element.id = "";
        }
    }

    static fromJson(json) {
        //console.log("inventory assembler fromJson", json);
        const baseOrder = DocBase.fromJson(json);

        const instance = new InventoryAssembler({
            srcWareHouse: new WareHouse({
                id: Util.jsonToString(json['srcStorageId']),
                name: Util.jsonToString(json['fromStorageName']),
            }),
            targetWareHouse: new WareHouse({
                id: Util.jsonToString(json['targetStorageId']),
                name: Util.jsonToString(json['toStorageName']),
            }),
            orgCommodityBatch: [],
            newCommodityBatch: [],
            cost: Util.jsonToCsFundDouble(json['cost'], 0),
            id: baseOrder.id,
            storeId: baseOrder.storeId,
            storeName: baseOrder.storeName,
            title: baseOrder.title,
            docCode: baseOrder.docCode,
            status: baseOrder.status,
            parentDocType: baseOrder.parentDocType,
            parentDocCode: baseOrder.parentDocCode,
            parentDocTitle: baseOrder.parentDocTitle,
            sourceDocType: baseOrder.sourceDocType,
            sourceDocCode: baseOrder.sourceDocCode,
            sourceDocTitle: baseOrder.sourceDocTitle,
            operator: baseOrder.operator,
            operatorId: baseOrder.operatorId,
            docMaker: baseOrder.docMaker,
            remark: baseOrder.remark,
            recordDate: baseOrder.recordDate
        });

        Object.assign(instance, baseOrder);

        const batchInRecords = json['orgDetails'] || [];
        for (const element of batchInRecords) {
            instance._orgCommodityList.push(CommodityBatch.fromInventoryTransferJson(element));
            // 解析仓库信息，后台是1对多，仓库信息在商品中
            if (instance.srcWareHouse.id === "" &&
                element['storageId'] != null &&
                element['storageName'] != null) {
                instance.srcWareHouse = new WareHouse({
                    id: Util.jsonToString(element['storageId']),
                    name: Util.jsonToString(element['storageName']),
                });
            }
        }

        const newBatchRecords = json['newDetails'] || [];
        for (const element of newBatchRecords) {
            instance._newCommodityList.push(CommodityBatch.fromInventoryTransferJson(element));
            // 解析仓库信息，后台是1对多，仓库信息在商品中
            if (instance.targetWareHouse.id === "" &&
                element['storageId'] != null &&
                element['storageName'] != null) {
                instance.targetWareHouse = new WareHouse({
                    id: Util.jsonToString(element['storageId']),
                    name: Util.jsonToString(element['storageName']),
                });
            }
        }

        return instance;
    }

    _$InventoryAssemblerToJson() {
        const ret = super.toJson();

        ret["cost"] = this.cost.value;

        ret['orgDetails'] = [];

        for (const element of this._orgCommodityList) {
            const item = {};
            item['changeCount'] = element.count.value;
            item['commodityId'] = element.commodity.commodityId;
            item['storageId'] = this.srcWareHouse.id;
            item['id'] = element.id;
            item['orderId'] = this.id;
            item['specId'] = element.commodity.id;

            ret['orgDetails'].push(item);
        }

        ret['newDetails'] = [];

        for (const element of this._newCommodityList) {
            const item = {};
            item['changeCount'] = element.count.value;
            item['commodityId'] = element.commodity.commodityId;
            item['id'] = element.id;
            item['orderId'] = this.id;
            item['specId'] = element.commodity.id;
            item['storageId'] = this.targetWareHouse.id;

            ret['newDetails'].push(item);
        }
        // console.log("inventory assembler to json:", ret);
        return ret;
    }

    toJson() {
        return this._$InventoryAssemblerToJson();
    }

    /// 打印信息
    _$InventoryAssemblerToPrintInfoJson() {
        const ret = {};
        ret['orgDetails'] = [];

        for (const element of this._orgCommodityList) {
            const item = {};
            item['changeCount'] = element.count.value;
            item['commodityId'] = element.commodity.commodityId;
            item['commodityName'] = element.commodity.name;
            item['fromStorageId'] = this.srcWareHouse.id;
            item['fromStorageName'] = this.srcWareHouse.name;
            item['id'] = element.id;
            item['orderId'] = this.id;
            item['specId'] = element.commodity.id;
            item['toStorageId'] = this.targetWareHouse.id;
            item['toStorageName'] = this.targetWareHouse.name;

            ret['orgDetails'].push(item);
        }

        ret['newDetails'] = [];

        for (const element of this._newCommodityList) {
            const item = {};
            item['changeCount'] = element.count.value;
            item['commodityId'] = element.commodity.commodityId;
            item['commodityName'] = element.commodity.name;
            item['fromStorageId'] = this.srcWareHouse.id;
            item['fromStorageName'] = this.srcWareHouse.name;
            item['id'] = element.id;
            item['orderId'] = this.id;
            item['specId'] = element.commodity.id;
            item['toStorageId'] = this.targetWareHouse.id;
            item['toStorageName'] = this.targetWareHouse.name;

            ret['newDetails'].push(item);
        }

        ret['id'] = this.id;
        ret['orderStatus'] = Object.values(CommonOrderStatus).indexOf(this.status); //单据状态：0待审核,1审核通过，2不通过，3已完成
        ret["orderTitle"] = this.title;
        ret['orderType'] = Object.values(DocType).indexOf(this.docType);

        ret['businessTime'] = this.operateDate.toString();

        ret['orgId'] = Engine.profile?.org?.orgId;

        ret['updateUser'] = this.updateor;
        ret['remark'] = this.remark;

        // 经办人
        ret['handleUserName'] = this.operator;
        ret['handleUserId'] = this.operatorId;

        ret["updateTime"] = this.updateDate;

        // print('inventory in param:' + ret.toString());

        return ret;
    }

    toPrintInfoJson() {
        return this._$InventoryAssemblerToPrintInfoJson();
    }
}